package com.ruge.date;


import com.ruge.excel.utils.RegularUtils;
import org.apache.commons.lang3.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 爱丽丝、如歌  创建于 2018/10/16 9:30
 * 说明:  日期工具类
 */
public class DateUtil {
	public static final String DATE_FORMAT_DAY = "yyyy-MM-dd";
	public static final String DATE_FORMAT_DAY_2 = "yyyy/MM/dd";
	public static final String DATE_FORMAT_DAY_3 = "MM-dd";
	public static final String DATE_FORMAT_DAY_CRON = "ss mm HH dd MM ? yyyy";
	public static final String TIME_FORMAT_SEC = "HH:mm:ss";
	public static final String DATE_FORMAT_SEC = "yyyy-MM-dd HH:mm:ss";
	public static final String DATE_FORMAT_MSEC = "yyyy-MM-dd HH:mm:ss.SSS";
	public static final String DATE_FORMAT_MSEC_T = "yyyy-MM-dd'T'HH:mm:ss.SSS";
	public static final String DATE_FORMAT_MSEC_T_Z = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
	public static final String DATE_FORMAT_DAY_SIMPLE = "y/M/d";

	/**
	 * 匹配yyyy-MM-dd
	 */
	private static final String DATE_REG = "^[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$";
	/**
	 * 匹配yyyy/MM/dd
	 */
	private static final String DATE_REG_2 = "^[1-9]\\d{3}/(0[1-9]|1[0-2])/(0[1-9]|[1-2][0-9]|3[0-1])$";
	/**
	 * 匹配y/M/d
	 */
	private static final String DATE_REG_SIMPLE_2 = "^[1-9]\\d{3}/([1-9]|1[0-2])/([1-9]|[1-2][0-9]|3[0-1])$";
	/**
	 * 匹配HH:mm:ss
	 */
	private static final String TIME_SEC_REG = "^(20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d$";
	/**
	 * 匹配yyyy-MM-dd HH:mm:ss
	 */
	private static final String DATE_TIME_REG = "^[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])\\s" +
			"(20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d$";
	/**
	 * 匹配yyyy-MM-dd HH:mm:ss.SSS
	 */
	private static final String DATE_TIME_MSEC_REG = "^[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])\\s" +
			"(20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d\\.\\d{3}$";
	/**
	 * 匹配yyyy-MM-dd'T'HH:mm:ss.SSS
	 */
	private static final String DATE_TIME_MSEC_T_REG = "^[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T" +
			"(20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d\\.\\d{3}$";
	/**
	 * 匹配yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
	 */
	private static final String DATE_TIME_MSEC_T_Z_REG = "^[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T" +
			"(20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d\\.\\d{3}Z$";
/**
 * ----------------------------日期工具类转换开始---------------------------------------------------
 */
	/**
	 * @param strDate 字符串
	 * @return 转换后的时间
	 * @Title: getDateByString
	 * @Description: 字符串转换成时间
	 * @author: wu_jian
	 * @date: 2018年10月18日 上午10:03:21
	 */
	public static Date getDateByString(String strDate) {
		Date parse = null;
		try {
			strDate = strDate.trim();
			SimpleDateFormat sdf = null;
			if (RegularUtils.isMatched(strDate, DATE_REG)) {
				sdf = new SimpleDateFormat(DATE_FORMAT_DAY);
			}
			if (RegularUtils.isMatched(strDate, DATE_REG_2)) {
				sdf = new SimpleDateFormat(DATE_FORMAT_DAY_2);
			}
			if (RegularUtils.isMatched(strDate, DATE_REG_SIMPLE_2)) {
				sdf = new SimpleDateFormat(DATE_FORMAT_DAY_SIMPLE);
			}
			if (RegularUtils.isMatched(strDate, TIME_SEC_REG)) {
				sdf = new SimpleDateFormat(TIME_FORMAT_SEC);
			}
			if (RegularUtils.isMatched(strDate, DATE_TIME_REG)) {
				sdf = new SimpleDateFormat(DATE_FORMAT_SEC);
			}
			if (RegularUtils.isMatched(strDate, DATE_TIME_MSEC_REG)) {
				sdf = new SimpleDateFormat(DATE_FORMAT_MSEC);
			}
			if (RegularUtils.isMatched(strDate, DATE_TIME_MSEC_T_REG)) {
				sdf = new SimpleDateFormat(DATE_FORMAT_MSEC_T);
			}
			if (RegularUtils.isMatched(strDate, DATE_TIME_MSEC_T_Z_REG)) {
				sdf = new SimpleDateFormat(DATE_FORMAT_MSEC_T_Z);
			}
			if (null != sdf) {
				parse = sdf.parse(strDate);
			}
		} catch (Exception e) {
			throw new RuntimeException("不能匹配正确的时间格式" + strDate);
		}
		return parse;
	}

	/**
	 * @param l long类型
	 * @return
	 * @Title: getDateByLong
	 * @Description: long类型转Date
	 * @author: wu_jian
	 * @date: 2018年10月19日 下午4:00:01
	 */
	public static Date getDateByLong(long l) {
		Date date = new Date(l);
		return date;
	}

	/**
	 * @param str 时间字符串
	 * @return 获取当前时间的毫秒值
	 */
	public static Long getLongByString(String str) {
		Date date = getDateByString(str);
		return date.getTime();
	}

	/**
	 * @param date 时间
	 * @return 获取当前时间的毫秒值
	 */
	public static Long getLongByDate(Date date) {
		return date.getTime();
	}

	/**
	 * @param l    时间戳
	 * @param type 1:yyyy-MM-dd  2:yyyy-MM-dd HH:mm:ss 3:yyyy-MM-dd HH:mm:ss.SSS
	 * @return
	 * @Title: getStringByLong
	 * @Description: 时间戳的字符串
	 * @author: wu_jian
	 * @date: 2018年10月19日 下午4:00:33
	 */
	public static String getStringByLong(Long l, int type) {
		String pattern = "";
		switch (type) {
			case 1:
				pattern = DATE_FORMAT_DAY;
				break;  //yyyy-MM-dd
			case 2:
				pattern = DATE_FORMAT_SEC;
				break;  //yyyy-MM-dd HH:mm:ss
			case 3:
				pattern = DATE_FORMAT_MSEC;
				break; //yyyy-MM-dd HH:mm:ss.SSS
			default:
				break;
		}
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		Date date = new Date(l);
		return sdf.format(date);
	}

	/**
	 * @param date 日期
	 * @param type 1:yyyy-MM-dd  2:yyyy/MM/dd  3:yyyy-MM-dd HH:mm:ss  4:yyyy-MM-dd HH:mm:ss.SSS  5:MM-dd
	 * @return
	 * @Title: getStringByDate
	 * @Description: 日期字符串
	 * @author: wu_jian
	 * @date: 2018年10月19日 下午4:01:14
	 */
	public static String getStringByDate(Date date, int type) {
		String pattern = "";
		switch (type) {
			case 1:
				pattern = DATE_FORMAT_DAY;
				break; //yyyy-MM-dd
			case 2:
				pattern = DATE_FORMAT_DAY_2;
				break; //yyyy/MM/dd
			case 3:
				pattern = DATE_FORMAT_SEC;
				break; //yyyy-MM-dd HH:mm:ss
			case 4:
				pattern = DATE_FORMAT_MSEC;
				break; //yyyy-MM-dd HH:mm:ss.SSS
			case 5:
				pattern = DATE_FORMAT_DAY_3;
				break; //MM-dd
			default:
				;
				break;
		}
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		return sdf.format(date);
	}

	/**
	 * 日期转cron表达式
	 *
	 * @param date 日期
	 * @return cron表达式
	 */
	public static String getCronByDate(Date date) {
		String pattern = DATE_FORMAT_DAY_CRON;
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		return sdf.format(date);
	}

	/**
	 * cron表达式 转 Date
	 * @param cron cron表达式
	 * @return Date类型的数据
	 */
	public static Date getDateByCron(String cron) {
		String pattern = DATE_FORMAT_DAY_CRON;
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		Date date = null;
		try {
			date = sdf.parse(cron);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return date;
	}

	/**
	 * ----------------------------日期工具类计算开始---------------------------------------------------
	 */
	/**
	 * @param start 开始时间
	 * @param end   结束时间
	 * @param type  1:毫秒  2:秒  3:分钟  4:小时  5:天  6:月  7:年
	 * @return
	 * @Title: getBewteenLongByDate
	 * @Description: 计算间隔类型
	 * @author: wu_jian
	 * @date: 2018年10月19日 下午4:02:13
	 */
	public static Long getBewteenLongByDate(String start, String end, int type) {
		long time = getDateByString(end).getTime() - getDateByString(start).getTime();
		switch (type) {
			case 1:
				time = time;
				break;                          //毫秒
			case 2:
				time = time / 1000;
				break;                     //秒
			case 3:
				time = time / 1000 / 60;
				break;                  //分钟
			case 4:
				time = time / 1000 / 60 / 60;
				break;               //小时
			case 5:
				time = time / 1000 / 60 / 60 / 24;
				break;            //天
			case 6:
				time = time / 1000 / 60 / 60 / 24 / 30;
				break;         //月
			case 7:
				time = time / 1000 / 60 / 60 / 24 / 30 / 12;
				break;      //年
			default:
				break;
		}
		return time;
	}

	/**
	 * @param start 开始时间
	 * @param end   结束时间
	 * @param rule  0:每天  1:周一  2:周二  3:周三  4:周四  5:周五  6:周六  7:周日  8:月末  9:年末
	 * @return 计算间隔类型
	 * @Title: getBewteenStringByDate
	 * @Description: 计算间隔类型
	 * @author: wu_jian
	 * @date: 2018年10月19日 下午4:03:06
	 */
	public static List<String> getBewteenStringByDate(String start, String end, int rule) {
		int tmp = 0;
		List<String> days = new ArrayList<String>();
		Calendar tempStart = Calendar.getInstance();
		tempStart.setTime(getDateByString(start));
		Calendar tempEnd = Calendar.getInstance();
		tempEnd.setTime(getDateByString(end));
		tempEnd.add(Calendar.DATE, +1);// 日期加1(包含结束)
		while (tempStart.before(tempEnd)) {
			switch (rule) {
				case 0:
					days.add(getStringByDate(tempStart.getTime(), 1));
					break;   //每天
				case 1:
					if ((tempStart.get(Calendar.DAY_OF_WEEK)) == 2) {
						days.add(getStringByDate(tempStart.getTime(), 1));
					}
					break; // 周一
				case 2:
					if ((tempStart.get(Calendar.DAY_OF_WEEK)) == 3) {
						days.add(getStringByDate(tempStart.getTime(), 1));
					}
					break; // 周二
				case 3:
					if ((tempStart.get(Calendar.DAY_OF_WEEK)) == 4) {
						days.add(getStringByDate(tempStart.getTime(), 1));
					}
					break; // 周三
				case 4:
					if ((tempStart.get(Calendar.DAY_OF_WEEK)) == 5) {
						days.add(getStringByDate(tempStart.getTime(), 1));
					}
					break; // 周四
				case 5:
					if ((tempStart.get(Calendar.DAY_OF_WEEK)) == 6) {
						days.add(getStringByDate(tempStart.getTime(), 1));
					}
					break; // 周五
				case 6:
					if ((tempStart.get(Calendar.DAY_OF_WEEK)) == 7) {
						days.add(getStringByDate(tempStart.getTime(), 1));
					}
					break; // 周六
				case 7:
					if ((tempStart.get(Calendar.DAY_OF_WEEK)) == 1) {
						days.add(getStringByDate(tempStart.getTime(), 1));
					}
					break; // 周日
				case 8:
					if (isEndOfMonth(tempStart.getTime())) {
						days.add(getStringByDate(tempStart.getTime(), 1));
					}
					;
					break;
				case 9:
					if (isEndOfSeason(tempStart.getTime())) {
						days.add(getStringByDate(tempStart.getTime(), 1));
					}
					;
					break;
				default:
					break;
			}
			tempStart.add(Calendar.DAY_OF_YEAR, 1);
		}
		return days;
	}

	/**
	 * ----------------------------日期工具类判断开始---------------------------------------------------
	 */
	/**
	 * @param date 当前日期
	 * @return 判断日期是否是月末
	 */
	public static boolean isEndOfMonth(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		if (calendar.get(Calendar.DATE) == calendar.getActualMaximum(Calendar.DAY_OF_MONTH)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * @param date 当前日期
	 * @return 判断日期是否是季末
	 */
	public static boolean isEndOfSeason(Date date) {
		String s = getStringByDate(date, 5);
		if (StringUtils.equals("03-31", s) || StringUtils.equals("06-30", s) || StringUtils.equals("09-30", s) || StringUtils.equals("12-31", s)) {
			return true;
		} else {
			return false;
		}
	}

}
